package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.AroundSign;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.LineSign;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 堵路狙击棋房间
 */
public class BlockRoadFightingRoom extends Room {
    int[][] dxdy = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    int inner_step = 0;
    Map<Integer, MovePos> canMovePos = new HashMap<>();
    List<Sign> curPlayerSignList = new ArrayList<>();


    protected int[] blackLastPoint = null; //黑棋上次的落点，赋值时必定赋长度为2的数组，分别是row，col
    protected int[] whiteLastPoint = null; //白棋上次的落点

    public BlockRoadFightingRoom(String roomName) {
        super(roomName, "\t\t夏日的新棋，反复走位，放置障碍，将对方逼入死角！\n\t\t双方棋子轮流「直一走法」无限次，移动后放置一枚障碍，双方棋子不能照面。","堵路狙击", BoardStyleData.BLOCK_ROAD_STYLE_10x10, true, true);
    }

    @Override
    public String getRuleText() {
        return "黑白双方均有1枚帅；\n" +
                "\n" +
                "轮流：\n" +
                "按照「直一」走法，走棋无限次；\n" +
                "移动后，在棋盘上放置一个障碍\n" +
                "\n" +
                "任何时候，双方帅不得照面\n" +
                "落败条件：无法移动";
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        inner_step = 0;
        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[0].length; j++) {
                if (curGrids[i][j] == 1) {
                    blackLastPoint = new int[]{i, j};
                } else if (curGrids[i][j] == 2) {
                    whiteLastPoint = new int[]{i, j};
                }
            }
        }
        curPlayerSignList.clear();
        updateNextCanMove(blackLastPoint[0], blackLastPoint[1], whiteLastPoint[0], whiteLastPoint[1]);
        showSign();
    }

    @Override
    public void doRule(int row, int col, int value) {
        // System.out.println("do rule");
        if (curGrids[row][col] != 0) {
            return;
        }
        if (inner_step % 2 == 0) {
            int index = getIndex(row, col);
            if (!canMovePos.containsKey(index)) {
                // System.out.println("can not move");
                return;
            }
            curPlayerSignList.clear();
            int to_index = index;
            int style = 1;
            while (canMovePos.containsKey(to_index)) {
                MovePos pos = canMovePos.get(to_index);
                int from_index = pos.from_index;
                curPlayerSignList.add(new LineSign(from_index, to_index, "#66FF0000", style));
                if (style == 1) {
                    style = 0;
                }
                to_index = from_index;
            }
            canMovePos.clear();
            // System.out.println("can move");
            curGrids[row][col] = value;
            curUpdateLastPoint(row, col);
            curPlayerSignList.add(new AroundSign(index, "#00000000", "#CC00FF00", 3f));
        } else {
            curGrids[row][col] = 9;
            curPlayerSignList.add(new AroundSign(getIndex(row, col), "#00000000", "#CC00FF00", 3f));
        }
        inner_step++;
        noticeAllRefreshGameInfo();
        if (inner_step % 2 == 0) {
            stepAdd();;
            // 绘制可移动的范围
            if (cur == 1) {
                updateNextCanMove(whiteLastPoint[0], whiteLastPoint[1], blackLastPoint[0], blackLastPoint[1]);
                if (canMovePos.size() == 0) {
                    doOver(WinMode.BLACK_WIN, curWin());
                    return;
                }
                showSign();
                noticeWhiteMove();
            } else {
                updateNextCanMove(blackLastPoint[0], blackLastPoint[1], whiteLastPoint[0], whiteLastPoint[1]);
                if (canMovePos.size() == 0) {
                    doOver(WinMode.WHITE_WIN, curWin());
                    return;
                }
                showSign();
                noticeBlackMove();
            }
        }
    }

    private String curWin() {
        if (cur == 1) {
            return player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp();
        } else if (cur == 2) {
            return player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp();
        } else {
            return "";
        }
    }

    // 判断位置在棋盘上
    protected boolean isInGrids(int row, int col) {
        return row >= 0 && row <= curGrids.length - 1 && col >= 0 && col <= curGrids[0].length - 1;
    }

    private void curUpdateLastPoint(int row, int col) {
        if (cur == 1) {
            curGrids[blackLastPoint[0]][blackLastPoint[1]] = 0;
            blackLastPoint = new int[]{row, col};
        } else if (cur == 2) {
            curGrids[whiteLastPoint[0]][whiteLastPoint[1]] = 0;
            whiteLastPoint = new int[]{row, col};
        }
    }

    private void updateNextCanMove(int from_x, int from_y, int enemy_x, int enemy_y) {
        canMovePos.clear();

        int[][] tmpGrids = GridsUtils.copyGrids(curGrids);
        for (int i = 0; i < 4; i++) {
            int dx = dxdy[i][0];
            int dy = dxdy[i][1];
            int x = enemy_x + dx;
            int y = enemy_y + dy;
            while (isInGrids(x, y)) {
                if (tmpGrids[x][y] != 0) {
                    break;
                }
                tmpGrids[x][y] = 9;
                x += dx;
                y += dy;
            }
        }
        int[][] canReach = new int[tmpGrids.length * tmpGrids[0].length][2];
        int head = 0;
        int tail = 1;
        canReach[0] = new int[]{from_x, from_y};
        tmpGrids[from_x][from_y] = 9;
        while (head < tail) {
            int x = canReach[head][0];
            int y = canReach[head][1];
            head++;
            for (int i = 0; i < 4; i++) {
                int tmp_x = x + dxdy[i][0];
                int tmp_y = y + dxdy[i][1];
                if (isInGrids(tmp_x, tmp_y) && tmpGrids[tmp_x][tmp_y] == 0) {
                    int index = getIndex(tmp_x, tmp_y);
                    canMovePos.put(index, new MovePos(index, getIndex(x, y)));
                    canReach[tail] = new int[]{tmp_x, tmp_y};
                    tmpGrids[tmp_x][tmp_y] = 9;
                    tail++;
                }
            }
        }
    }

    private void showSign() {
        signList.clear();
        for (int index : canMovePos.keySet()) {
            signList.add(new ColorSign(index, "#9988EE88"));
        }
        signList.addAll(curPlayerSignList);
    }

    private static class MovePos {
        public int index;
        public int from_index;

        MovePos(int _index, int _from_index) {
            index = _index;
            from_index = _from_index;
        }
    }
}
